package top.codef.secure.handlers;

import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.AuthorizationServiceException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.csrf.InvalidCsrfTokenException;
import org.springframework.security.web.csrf.MissingCsrfTokenException;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.codef.secure.pojomodel.SecureResponseEnum;
import top.codef.secure.properties.CerberusExceptionProperties;

public class CerberusAccessDeniedHandler implements AccessDeniedHandler {

	private static final Log logger = LogFactory.getLog(CerberusAccessDeniedHandler.class);

	private final ObjectMapper objectMapper;

	private final CerberusExceptionProperties cerberusExceptionProperties;

	private final String CONTENT_TYPE = "application/json; charset=utf-8";

	public CerberusAccessDeniedHandler(ObjectMapper objectMapper,
			CerberusExceptionProperties cerberusExceptionProperties) {
		this.objectMapper = objectMapper;
		this.cerberusExceptionProperties = cerberusExceptionProperties;
	}

	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException, ServletException {

		response.setContentType(CONTENT_TYPE);
		if (accessDeniedException instanceof InvalidCsrfTokenException) {
			response.setStatus(cerberusExceptionProperties.getInvalidateCsrfToken().value());
			response.getWriter().write(objectMapper
					.writeValueAsString(SecureResponseEnum.ACCESS_DENIED.createSecureModel("错误的csrfToken")));
		} else if (accessDeniedException instanceof MissingCsrfTokenException) {
			response.setStatus(cerberusExceptionProperties.getMissingCsrfToken().value());
			response.getWriter().write(
					objectMapper.writeValueAsString(SecureResponseEnum.ACCESS_DENIED.createSecureModel("csrfToken缺失")));
		} else if (accessDeniedException instanceof AuthorizationServiceException) {
			response.setStatus(cerberusExceptionProperties.getNotAuthorize().value());
			response.getWriter().write(
					objectMapper.writeValueAsString(SecureResponseEnum.ACCESS_DENIED.createSecureModel("权限验证异常")));
		} else {
			logger.info("access denied", accessDeniedException);
			response.setStatus(cerberusExceptionProperties.getOtherAccessDenied().value());
			response.getWriter().write(
					objectMapper.writeValueAsString(SecureResponseEnum.ACCESS_DENIED.createSecureModel("拒绝被访问")));
		}

	}

}
